package ch.bfh.fbi.mobicomp.zap04;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import ch.quantasy.android.speech.SpeechService;
import ch.quantasy.android.speech.string.FrenchString;
import ch.quantasy.android.speech.string.GermanString;
import ch.quantasy.android.speech.string.UKString;

/**
 * Zap03 does not work (ANR), as it simply uses too much CPU-Time from the
 * Broadcasts origin context (thread). Furthermore the algorithm is within the
 * BroadcastReceiver. In general, this is not a good idea, as this example with
 * two broadcastReceivers demonstrates. So the algorithm is put into a Service.
 * 
 * @author quantasy
 * 
 */
public class Zap04Service extends Service {
	public static final String REMOTE_ZAPPER_ACTION = "ch.bfh.fbi.mobicomp.zap04.Zap04Service.REMOTE_ZAPPER_ACTION";
	public static final String ZAPPER_KEY_WORD = "ZAP:";
	private static final String destructionKey = "destroyMe";
	private static final String haltKey = "stopDestroyMe";

	private final Intent speechIntent;
	private long countdown;

	private static final String TAG = "ZAP05";

	public static Intent getZapperIntent(final String message) {
		Intent intent = null;
		if (message.startsWith(Zap04Service.ZAPPER_KEY_WORD)) {
			intent = new Intent(Zap04Service.REMOTE_ZAPPER_ACTION);
			intent.putExtra("message",
					message.substring(Zap04Service.ZAPPER_KEY_WORD.length()));
		}
		return intent;
	}

	public Zap04Service() {
		this.speechIntent = SpeechService.getSpeechIntent();
	}

	@Override
	public IBinder onBind(final Intent intent) {
		// We do not want to grand explicite access!
		return null;
	}

	@Override
	public int onStartCommand(final Intent intent, final int flags,
			final int startId) {
		Log.d(Zap04Service.TAG, "Service Intent received: " + intent);
		if (intent == null) {
			return super.onStartCommand(intent, flags, startId);
		}
		if (Zap04Service.destructionKey.equals(intent.getExtras().getString(
				"message"))) {
			Log.d(Zap04Service.TAG, "destruction initiated...");
			this.initiateAutoDestruction();

			Log.d(Zap04Service.TAG, "Start");
		} else if (Zap04Service.haltKey.equals(intent.getExtras().getString(
				"message"))) {
			Log.d(Zap04Service.TAG, "destruction aborted...");
			this.resetAutoDestruction();
			Log.d(Zap04Service.TAG, "stop");
		}

		else {
			Log.d(Zap04Service.TAG, "unknown command.");
		}

		return super.onStartCommand(intent, flags, startId);
	}

	private void resetAutoDestruction() {
		if (this.countdown == 0) {
			return;
		}
		Thread.currentThread().interrupt();
		this.countdown = 0;

		SpeechService.setPhrase(this.speechIntent, new UKString(
				"Self destruction sequence aborted."), new GermanString(
				"Selbstzerstörungssequenz abgebrochen."), new FrenchString(
				"Séquence d'autodestruction avortée."));
		this.startService(this.speechIntent);
	}

	private void initiateAutoDestruction() {
		if (this.countdown != 0) {
			return;
		}
		this.countdown = System.currentTimeMillis() + (3 * 60 * 1000);
		SpeechService.setPhrase(this.speechIntent, new UKString(
				"Self destruction sequence initiated."), new GermanString(
				"Selbstzerstörungs Sequenz eingeleitet."), new FrenchString(
				"Séquence d'autodestruction declanchée."));
		this.startService(this.speechIntent);
		this.countDown();
	}

	private void countDown() {
		try {
			int timeLeft = (int) ((this.countdown - System.currentTimeMillis()) / 1000);
			while (timeLeft > 70) {
				this.minutesCount(timeLeft);
				Thread.sleep(60000); // 1 Minute
				timeLeft = (int) ((this.countdown - System.currentTimeMillis()) / 1000);
			}
			while (timeLeft > 11) {
				this.secondsBlockCount(timeLeft);
				Thread.sleep(10000); // 10 Seconds
				timeLeft = (int) ((this.countdown - System.currentTimeMillis()) / 1000);
			}
			while (timeLeft > 0) {
				this.secondsCount(timeLeft);
				Thread.sleep(1000); // 1 Second
				timeLeft = (int) ((this.countdown - System.currentTimeMillis()) / 1000);
			}
			this.destroy();
		} catch (final InterruptedException ex) {
		}
	}

	private void minutesCount(final int timeLeft) {
		SpeechService.setPhrase(this.speechIntent, new UKString(""
				+ (1 + (timeLeft / (60))) + "Minutes until self destruction"),
				new GermanString("" + (1 + (timeLeft / (60)))
						+ "Minuten bis zur Selbstzerstörung"),
				new FrenchString("" + (1 + (timeLeft / (60)))
						+ "minutes jusqu'à ce que l'auto-destruction"));
		this.startService(this.speechIntent);
	}

	private void secondsBlockCount(final int timeLeft) {
		if ((timeLeft % 3) == 0) {
			SpeechService.setPhrase(this.speechIntent, new UKString(""
					+ (10 + ((timeLeft / 10) * 10))
					+ "Seconds until self destruction"));
		} else if ((timeLeft % 3) == 1) {
			SpeechService.setPhrase(this.speechIntent, new GermanString(""
					+ (10 + ((timeLeft / 10) * 10))
					+ "Sekunden bis zur Selbstzerstörung"));
		} else {
			SpeechService.setPhrase(this.speechIntent, new FrenchString(""
					+ (10 + ((timeLeft / 10) * 10))
					+ "seconds jusqu'à ce que l'auto-destruction"));
		}
		this.startService(this.speechIntent);
	}

	private void secondsCount(final int timeLeft) {
		SpeechService.setPhrase(this.speechIntent,
				new UKString("" + (timeLeft)));
		this.startService(this.speechIntent);
	}

	private void destroy() {
		this.countdown = 0;
		SpeechService.setPhrase(this.speechIntent, new UKString(
				"Self destroying now."));
		this.startService(this.speechIntent);
	}
}
